#include "stdafx.h"
#include <stdlib.h>
#include "NetworkHandler.h"


// DEFINE  
#define DEFAULT_SERVER_PORT	6458
#define ECHO_BUF_LENGTH		512

NetworkHandler::NetworkHandler(void) : serverIPAdd("192.168.0.101"), serverPort(DEFAULT_SERVER_PORT)
{
	char* buf = new char[ECHO_BUF_LENGTH];
	sprintf(buf, "server address == > %s:%d\n", serverIPAdd, serverPort);
	OutputDebugString(buf);
	delete[] buf;

	messages = std::queue<std::string>();
}

NetworkHandler::~NetworkHandler(void)
{
}
 
// reads data from the sockets and send it back
int NetworkHandler::clientActionUDP(SOCKET sockfd, struct sockaddr *serverAdd, int size, char *msg)
{
	int len;
	int rc;
	int i = 0, sLength; 

	//char *s = "this is a long string but not too long.  The idea is to send and recieve many small section of the string.  Therefore the buffer size will be small";
	char buf[ECHO_BUF_LENGTH]; // 256 is a magic number

	sLength = strlen(msg);
	while (i <= sLength)
	{
		// send the string until it has completed
		len = min(32,sLength-i);	// send 32 bytes at a time
		
		char* sendOutput = new char[ECHO_BUF_LENGTH];
		sprintf(sendOutput, "client sending == > %s\n", msg);
		//OutputDebugString(sendOutput);
		delete[] sendOutput;

		// note the number of bytes that were sent can be smaller than the requested number 
		rc = sendto(sockfd, &msg[i], len, 0, (struct sockaddr *)serverAdd, size);   
		if (rc == SOCKET_ERROR) {
			// error
			rc = -1;
			break;
		}
		i += len;
		if (rc != len) {
			// not all bytes were sent 
			// need loop
			rc = 5;
		}
		if(rc == 0) {
			//end of string
			shutdown(sockfd,1);
			break;
		}

		memset(buf, 0, ECHO_BUF_LENGTH);
		// note that we do not specify the socket address - due to the bind
		rc = recvfrom(sockfd, buf, ECHO_BUF_LENGTH, 0, (struct sockaddr *) NULL, (int *) NULL);    

		if (rc == 0) {
			// connecion is closed
			rc = 0;
			break;
		}
		if (rc == SOCKET_ERROR) {
			// error
			rc = -1;
			break;
		}

		// DEBUG: print client messages to console
		char* recieveInput = new char[ECHO_BUF_LENGTH];
		sprintf(recieveInput, "client received == > %s\n", buf);
		//OutputDebugString(recieveInput);
		delete[] recieveInput;

		messages.push(buf);
	}
	return(rc);
}

// send a message to the server
int NetworkHandler::send(char *msg)
{
	int rc = 0;
	SOCKET sockfd = INVALID_SOCKET;
	SOCKET clientSock = INVALID_SOCKET;
	struct sockaddr_in clientAdd, serverAdd;
	int clientAddLen = 0;

    // Start Winsock up
    WSAData wsaData;
    if ((rc = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0) {
		OutputDebugString("WSAStartup() returned error code.\n");
        return(1);
    }
	
	// open the socket - note we use datagrram 
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);	// service request will determine the protocol could be IPPRORTO_TCP
	if (sockfd == INVALID_SOCKET)
	{
		// error
		rc = -1;
		goto err;
	}

	// set the server information
	serverAdd.sin_family = AF_INET;
	serverAdd.sin_addr.S_un.S_addr = inet_addr(serverIPAdd.c_str());
	serverAdd.sin_port = htons(serverPort);		

	// set client information
	clientAdd.sin_family = AF_INET;
	clientAdd.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	clientAdd.sin_port = htons(0);		// allocate a dynamic address from the pool

	sizeof(clientAdd);
	rc = bind(sockfd, (struct sockaddr *) &clientAdd, sizeof(clientAdd));
	
	if (rc == SOCKET_ERROR) // error
	{
		rc = -1;
		goto err;
	}

	// read the information from socket and send it back to the client
	rc = clientActionUDP(sockfd, (sockaddr *) &serverAdd, sizeof(serverAdd), msg);

	if (rc != 0) { goto err; } // error

	return (rc);

err:
    // Shut Winsock back down and take off.
    if (sockfd != INVALID_SOCKET) {
		closesocket(sockfd);
	}
	
    if (clientSock != INVALID_SOCKET) {
		closesocket(clientSock);
	}
	WSACleanup();

	char* errorCode = new char[128];
	sprintf(errorCode, "ERROR:%d\n",rc);
	OutputDebugString(errorCode);
	delete[] errorCode;
	return (rc);
}


